package com.changgou.oauth.config;
import com.changgou.oauth.util.UserJwt;
import com.changgou.user.feign.UserFeign;
import entity.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;

import org.springframework.security.core.authority.AuthorityUtils;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/***
 * 这里一个问题就是，在把写死的改为从数据库加载后，发现去查询其他服务器，此时还没有生成令牌，也就没有
 * 权限去调用别的服务器，那我们就创建了一个feign拦截器，在发送feign之前，就拦截，创建一个令牌
 * 放在调用的头上，这样就可以查到对应的角色，或者密码等信息，则可以为其他请求生成令牌的人，生成令牌返回
 */
/**
 * 这里是对访问该安全认证的请求进行认证，通过则可以去生成对应的令牌给请求者，并且给与已经认证的标识
 */

/*****
 * 自定义授权认证类
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    ClientDetailsService clientDetailsService;

    @Autowired
    UserFeign userFeign;
    /****
     * 自定义授权认证
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //=================客户端信息认证starter=====================
        //取出身份，如果身份为空说明没有认证
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //没有认证统一采用httpbasic认证，httpbasic中存储了client_id和client_secret，开始认证client_id和client_secret
        if(authentication==null){
            //查询数据库   oauth_client_details
            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
            if(clientDetails!=null){
                //秘钥
                String clientSecret = clientDetails.getClientSecret();
                //静态方式
               /* return new User(username,new BCryptPasswordEncoder().encode(clientSecret),//客户端密钥==》加密操作
                        AuthorityUtils.commaSeparatedStringToAuthorityList("")); //权限
          */      //数据库查找方式
                return new User(username,  //客户端ID
                        clientSecret,    //客户端密钥--》加密操作
                        AuthorityUtils.commaSeparatedStringToAuthorityList(""));
            }
        }
        //=================客户端信息认证end=====================

        //=================用户账号信息密码认证starter=====================
        if (StringUtils.isEmpty(username)) {
            return null;
        }


        /***
         *从数据库中加载查询用户信息
         * 1，没有令牌，feign调用之前，生成令牌（admin）
         * 2，feign调用之前，令牌需要携带过去
         * 3，feign调用之前  ，令牌需要存放在header文件中
         * 4，请求-》feign调用-》拦截RequestInterceptor->feign调用之前执行拦截
         * 大概思路就是搞个拦截器，然后在调用feign的时候拦截，然后把令牌放进去
         */

        //客户端id：changgou
        //客户端密钥:changgou
        //普通用户账号-》》账号--》任意账号： 密码szitheima
        //根据用户名去数据库查询对应的信息
        Result<com.changgou.user.pojo.User> userResult = userFeign.findById(username);
        if (userResult==null || userResult.getData()==null){
            return null;
        }
        //根据用户名查询用户信息
        String pwd = userResult.getData().getPassword();//new BCryptPasswordEncoder().encode("szitheima");
        //创建User对象      //指定用户的角色信息   企业中是需要通过feign调用数据库查询对应的角色
        String permissions = "user,vip";


        UserJwt userDetails = new UserJwt(username,pwd,AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));


        //userDetails.setComy(songsi);
        //=================用户账号信息密码认证end=====================
        return userDetails;
    }
}
